   package org.yoyo.classroom.service;

   import org.springframework.beans.factory.annotation.Autowired;
   import org.springframework.stereotype.Service;
   import org.yoyo.classroom.domain.po.BookingDTO;
   import org.yoyo.classroom.domain.po.BookingOrder;
   import org.yoyo.classroom.domain.po.BookingRule;
   import org.yoyo.classroom.domain.po.ValidationResult;

   import java.time.LocalDate;
   import java.time.LocalDateTime;
   import java.time.LocalTime;
   import java.time.YearMonth;
   import java.time.format.DateTimeFormatter;
   import java.time.temporal.ChronoUnit;

   /**
    * Created with IntelliJ IDEA.
    *
    * @Author: cc
    * @Date: 2024/12/13/13:36
    **/
   // BookingValidationService.java
   @Service
   public class BookingValidationService {
       private static final DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm");
       private static final DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");


       @Autowired
       private BookingRuleService bookingRuleService;

       @Autowired
       private BookingRecordService bookingRecordService;

       /**
        * 校验预约参数
        * @param bookingDTO 预约请求参数
        * @return 校验结果
        */
       public ValidationResult validateBooking(BookingDTO bookingDTO) {
           // 获取自习室的预约规则
           BookingRule rule = bookingRuleService.getBookingRuleByRoomId(bookingDTO.getRoomId());
           if (rule == null) {
               return ValidationResult.error("该自习室未设置预约规则");
           }

           // 1. 校验预约时间是否在允许的时间段内
           LocalTime startTime = LocalTime.parse(bookingDTO.getStartTime());
           LocalTime endTime = LocalTime.parse(bookingDTO.getEndTime());
           LocalTime ruleStartTime = rule.getStartTime();
           LocalTime ruleEndTime = rule.getEndTime();

           if (startTime.isBefore(ruleStartTime) || endTime.isAfter(ruleEndTime)) {
               return ValidationResult.error(String.format("预约时间必须在 %s - %s 之间",
                       rule.getStartTime(), rule.getEndTime()));
           }

           // 2. 校验预约时长是否超过最大限制
           long hours = ChronoUnit.HOURS.between(startTime, endTime);
           if (hours > rule.getMaxHoursPerBooking()) {
               return ValidationResult.error(String.format("单次预约时长不能超过 %d 小时",
                       rule.getMaxHoursPerBooking()));
           }

           // 3. 校验预约日期是否超过最大提前天数
           LocalDate bookingDate = LocalDate.parse(bookingDTO.getBookingDate());
           LocalDate today = LocalDate.now();
           long daysAhead = ChronoUnit.DAYS.between(today, bookingDate);
           if (daysAhead > rule.getMaxDaysAhead()) {
               return ValidationResult.error(String.format("只能提前 %d 天预约",
                       rule.getMaxDaysAhead()));
           }

           // 4. 校验用户当月预约次数是否超限
           int monthlyBookings = bookingRecordService.countUserMonthlyBookings(
                   bookingDTO.getUserId(),
                   YearMonth.from(bookingDate)
           );
           if (monthlyBookings >= rule.getMaxBookingsPerMonth()) {
               return ValidationResult.error(String.format("当月预约次数已达上限 %d 次",
                       rule.getMaxBookingsPerMonth()));
           }
           // 5. 验证当前座位预约时间的状态  根据预约时间区间去找booking_order表里有没有seatId的记录，有表示已经被预约了
           // 创建 LocalDateTime 对象
           LocalDateTime startDateTime = LocalDateTime.of(bookingDate, startTime);
           LocalDateTime endDateTime = LocalDateTime.of(bookingDate, endTime);

           // 格式化 LocalDateTime 为所需的字符串格式
           String formattedStartDateTime = startDateTime.format(outputFormatter);
           String formattedEndDateTime = endDateTime.format(outputFormatter);
           bookingDTO.setStartTime(formattedStartDateTime);
           bookingDTO.setEndTime(formattedEndDateTime);

           BookingOrder conflictingOrders = bookingRecordService.findConflictingOrders(bookingDTO);
           if (conflictingOrders != null) {
               return ValidationResult.error(String.format("座位: %s 在预约时间: %s - %s 之间已经被预约了",
                       bookingDTO.getSeatId(), formattedStartDateTime, formattedEndDateTime));
           }
           return ValidationResult.success();
       }
   }
